﻿using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Xml;
using BlogsAPI.Interfaces;
using Newtonsoft.Json.Linq;

namespace BlogsAPI.Sites
{
    using System.Web;
    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Net;
    using System.Text;
    using System.Text.RegularExpressions;
    using Abstract;

    /// <summary>
    /// Videohost - Vimeo.com
    /// </summary>
    [BlogServiceAPI(Description = "Rutube", Link = "http://rutube.ru")]
    public class Rutube : BlogServer, IVideoHost
    {
        private static readonly Regex Validation = new Regex(@"^https?://(?:[-_\w]+\.)?rutube\.ru", Regexoptions);

        //https://rutube.ru/video/9ae7f548a6d61d672fd7d27d50a39a8d/
        private static readonly Regex rRutubeVideo = new Regex(@"^https?://(?:[-_\w]+\.)?rutube\.ru(?:/video)?/(\w+)(?:/|$)", Regexoptions);

        #region interface: BlogServer

        [DebuggerStepThrough]
        public Rutube()
        {
            Encoding = Encoding.UTF8;
        }

        /// <summary>
        /// Убираем параметры
        /// </summary>
        /// <param name="link"></param>
        /// <returns></returns>
        public override string ToCanonicalLink(string link)
        {
            //урезаем все параметры, поэтому не вызываем базовый тип
            link = link.Split(new[] { '?','@' }, 2, StringSplitOptions.None)[0];
            //убираем www
            link = link.Replace("/www.", "/").TrimEnd('/');
            return link;
        }

        /// <summary>
        /// проверка, является ли передаваемый урл чатью этого сервиса
        /// </summary>
        public override Boolean ValidateLink(String sLink)
        {
            return Validation.Match(sLink).Success;
        }

        /// <summary>
        /// проверка, является ли передаваемый урл чатью этого сервиса
        /// </summary>
        /// <param name="sLink">ссылка для проверки</param>
        /// <param name="userName">Имя пользователя на блогохостинге</param>
        /// <param name="bType">Тип блога - пользователь или сообщество</param>
        public override Boolean ValidateLink(String sLink, out String userName, out BlogType bType)
        {
            bType = BlogType.Unknown;
            userName = String.Empty;
            if (String.IsNullOrEmpty(sLink)) return false;
            bool bRet = ValidateLink(sLink);
            if (bRet)//проставляем имя блогера
            {
                MatchCollection mc = Regex.Matches(sLink, @"(?<=/)(\w{5,})(?:/|$)", Regexoptions);
                if (mc.Count == 1 || //rutube.ru/674663
                    mc.Cast<Match>().Any(m => String.Compare(m.Groups[1].Value,
                        "person", StringComparison.InvariantCultureIgnoreCase) == 0)) //rutube.ru/video/person/1004016
                {
                    userName = mc.Cast<Match>().Last().Groups[1].Value;
                }
            }
            return bRet;
        }

        /// <summary>
        /// Костыль, так как мы храним аватарки без нововведенных (/video/person/) в ссылке
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="btype"></param>
        /// <param name="forAvatar"></param>
        /// <returns></returns>
        public string GetBlogLink(string userName, BlogType btype, bool forAvatar)
        {
            if (forAvatar)
            {
                return String.Format("http://rutube.ru/{0}", userName);
            }else
            {
                return GetBlogLink(userName, btype);
            }
        }

        public override string GetBlogLink(string userName, BlogType btype)
        {
            return String.Format("http://rutube.ru/video/person/{0}", userName);
        }

        #endregion

        #region IVideoHost



        /// <summary>
        /// Получение данных по ссылке
        /// </summary>
        /// <param name="link"></param>
        /// <returns></returns>
        public Tuple<VideoData, BlogPost> GetVideoData(Uri link)
        {
            var oRet = new Tuple<VideoData, BlogPost>(
                new VideoData(link){ Published = DateTime.UtcNow.AddMonths(-1)},
                new BlogPost(link) { Existance = false, Links = 0, Comments = 0 });
            try
            {
                Match v = rRutubeVideo.Match(link.OriginalString);
                if (v.Success)
                {
                    Uri postlink;
                    if (Uri.TryCreate(String.Format("http://rutube.ru/api/video/{0}", v.Groups[1].Value),
                                      UriKind.Absolute, out postlink))
                    {
                        var myHttpWebRequest = (HttpWebRequest)WebRequest.Create(postlink);
                        myHttpWebRequest.AllowAutoRedirect = false;
                        var myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
                        if (myHttpWebResponse.StatusCode == HttpStatusCode.OK)
                        {
                            string reply = new StreamReader(myHttpWebResponse.GetResponseStream()).ReadToEnd();
                            //
                            JObject dataJS = JObject.Parse(reply);
                            //MatchCollection mc = Regex.Matches(reply, @"<([^>]+)>([^<]+)</", Regexoptions);
                            //var dataarray = (from i in mc.Cast<Match>()
                            //                 select new
                            //                     {
                            //                         name = i.Groups[1].Value,
                            //                         value = i.Groups[2].Value
                            //                     }).ToArray();
                            /////////
                            //Поставим картинки в самый конец, так как что-то тут не так =(
                            //Match img = rThumbnail2.Match(reply);
                            //var img = dataarray.FirstOrDefault(i => i.name == "thumbnail_url");
                            if (dataJS["thumbnails"] != null && dataJS["thumbnails"].HasValues && dataJS["thumbnails"]["small"] != null)
                            {
                                oRet.Item1.Replace = "<a href=\"" +
                                          link.OriginalString + "\"><img src=\"" + dataJS["thumbnails"]["middle"].Value<string>() +
                                          "\"/>[Видео]</a>";
                                oRet.Item1.Images += "<img src=\"" + dataJS["thumbnails"]["small"].Value<string>() + "\" width=\"120\" height=\"90\"/>";
                            }
                            else if (dataJS["thumbnail_url"] != null)
                            {
                                oRet.Item1.Replace = "<a href=\"" +
                                     link.OriginalString + "\"><img src=\"" + dataJS["thumbnail_url"].Value<string>() +
                                    "\"/>[Видео]</a>";
                                oRet.Item1.Images += "<img src=\"" + dataJS["thumbnail_url"].Value<string>().Replace("-1.", "-2.") + "\" width=\"120\" height=\"90\"/>";
                            }
                            //а теперь просмотры!
                            //Match vs = new Regex(@"<stats_number_of_plays>(\d+)<", Regexoptions).Match(reply);
                            //var views = dataarray.FirstOrDefault(i => i.name == "hits");
                            if (dataJS["hits"] != null)
                            {
                                oRet.Item1.Views += dataJS["hits"].Value<int>();
                            }
                            //Match pDate = new Regex(@"<upload_date>([^>]+)<", Regexoptions).Match(reply);
                            //var date = dataarray.FirstOrDefault(i => i.name == "created_ts");//created_ts
                            if (dataJS["created_ts"] != null)
                            {
                                //проблема в том, что время тут московское, поэтому сдвиг на 4 часа
                                oRet.Item1.Published = (dataJS["created_ts"].Value<DateTime>()).AddHours(-4);
                            }
                            //формирование поста...
                            //Match title = new Regex(@"<title>([^>]+)<", Regexoptions).Match(reply);
                            //var title = dataarray.FirstOrDefault(i => i.name == "title");
                            if (dataJS["title"] != null)// && Common.IsRussian(dataJS["title"].Value<string>()))
                            {
                                try
                                {
                                    //var selectSingleNode = xDoc.SelectSingleNode("//duration");
                                    //var duration = dataarray.FirstOrDefault(i => i.name == "duration");
                                    if (dataJS["duration"] != null)
                                    {
                                        oRet.Item1.Duration = Math.Max(oRet.Item1.Duration,
                                                                     dataJS["duration"].Value<uint>());
                                    }
                                    oRet.Item2.Existance = true;
                                    oRet.Item2.Published = oRet.Item1.Published;
                                    oRet.Item2.Views = oRet.Item1.Views;
                                    oRet.Item2.Links = 0;
                                    //oRet.Item2.Comments =
                                    //    int.Parse(
                                    //        xDoc.SelectSingleNode("//stats_number_of_comments").InnerText.
                                    //             Trim()); //stats_number_of_comments
                                    //var description = dataarray.FirstOrDefault(i => i.name == "description");
                                    if (dataJS["description"] != null)
                                    {
                                        oRet.Item2.Body = dataJS["description"].Value<string>();
                                    }
                                    oRet.Item1.About = oRet.Item2.Body;
                                    //oRet.Item2.SpecialParam = xDoc.SelectSingleNode("//user_id").InnerText;
                                    //var user_id = dataarray.FirstOrDefault(i => i.name == "id");
                                    if (dataJS["author"].HasValues && dataJS["author"]["id"] != null)
                                    {
                                        oRet.Item2.SpecialParam = dataJS["author"]["id"].Value<int>().ToString();
                                    }
                                    //oRet.Item2.Subject = xDoc.SelectSingleNode("//user_name").InnerText + ": " +
                                    //                     title.Groups[1].Value.Trim().Replace("логгер", "логер");
                                    //var username = dataarray.FirstOrDefault(i => i.name == "name");
                                    if (dataJS["author"].HasValues && dataJS["author"]["name"] != null)
                                    {
                                        oRet.Item2.Subject = dataJS["author"]["name"].Value<string>() + ": ";
                                    }
                                    oRet.Item2.Subject += dataJS["title"].Value<string>();
                                    oRet.Item1.Title = oRet.Item2.Subject;

                                    oRet.Item2.Attributes.Add(new PostAttribute(PostParams.Length, oRet.Item1.Duration));
                                    if (!String.IsNullOrEmpty(oRet.Item1.Images))
                                    {
                                        oRet.Item2.Attributes.Add(new PostAttribute(PostParams.MediaThumbnail,
                                            oRet.Item1.Images));
                                    }
                                    if (dataJS["author"].HasValues && dataJS["author"]["avatar_url"] != null)
                                    {
                                        oRet.Item2.Attributes.Add(new PostAttribute(PostParams.UserAvatar,
                                            dataJS["author"]["avatar_url"].Value<string>()));
                                    }
                                }
                                catch (Exception e1)
                                {
                                    Debug.Write(e1);
                                }
                            }
                        }
                        myHttpWebResponse.Close();
                    }
                }
            }
            catch (Exception e1)
            {
                Debug.Write(e1);
            }
            return oRet;
        }

        /// <summary>
        /// http://rutube.ru/api/oembed/?format=json&url=http://rutube.ru/video/f92c96b299e00ce47cef3ebe79a5d910/
        /// </summary>
        /// <param name="link"></param>
        /// <returns>HTML code for embed</returns>
        public string FormEmbedCode(Uri link, String adds = null)
        {
            string username;
            BlogType bt;
            if (ValidateLink(link.OriginalString,out username,out bt))
            {
                try
                {
                    //на конце обязательно необходим /
                    var req = MakeRequest("http://rutube.ru/api/oembed/?format=json&url=" + link.OriginalString.TrimEnd('/')+'/');
                    string reply = new StreamReader(req.GetResponse().GetResponseStream()).ReadToEnd();
                    JObject oData = JObject.Parse(reply);
                    return oData["html"].Value<string>();
                }
                catch (Exception e1)
                {
                    //если http://rutube.ru/video/9e00b818640d77acd93c3ae1c2e0a6bb/ просто разобъем по 'video'
                    var parts = link.OriginalString.Split(new[] {"/video/"}, StringSplitOptions.None);
                    if (parts.Length == 2)
                    {
                        username = parts[1].TrimEnd('/');
                    }
                    Debug.Write(e1);
                }
                //&autoStart=true
                return String.Format(
                    "<iframe width=\"720\" height=\"405\" src=\"http://rutube.ru/video/embed/{0}?wmode=direct\" frameborder=\"0\" webkitallowfullscreen=\"\" mozallowfullscreen=\"\" allowfullscreen=\"\" id=\"video_frame\"></iframe>",username);
            }
            return String.Empty;
        }

        #endregion
    }
}